#include <boost/asio.hpp>
#include <iostream>
#include <memory>
#include <set>

#define BUFFER_SIZE 1024

using namespace boost::asio::ip;

typedef std::shared_ptr<tcp::socket> socket_ptr;

std::set<std::shared_ptr<std::thread>> thread_set;

void session(socket_ptr socket) {
  try {
    for (;;) {
      char buffer[BUFFER_SIZE] = {0};
      boost::system::error_code ec;
      size_t receive_length =
          socket->receive(boost::asio::buffer(buffer, BUFFER_SIZE));

      //if (receive_length == 0) {
      //  std::cout << "connection closed by peer" << std::endl;
      //  break;
      //} else {
      //  throw boost::system::system_error(ec);
      //}
      std::cout << "receive from "
                << socket->remote_endpoint().address().to_string() << std::endl;
      std::cout << "receive message is " << buffer << std::endl;
      //回传信息值
      boost::asio::write(*socket, boost::asio::buffer(buffer, receive_length));

    }

  } catch (const std::exception &e) {
    std::cout << "Exception:" << e.what() << std::endl;
  }
}

// 启动服务器
void StartServer(boost::asio::io_context &ioc, unsigned short Port) {
  tcp::acceptor ap(ioc, tcp::endpoint(tcp::v4(), Port));
  for (;;) {
    socket_ptr socket(new tcp::socket(ioc));
    ap.accept(*socket);

    // 获取客户端连接的信息
    std::string client_address =
        socket->remote_endpoint().address().to_string();
    unsigned short client_port = socket->remote_endpoint().port();

     std::cout << "Client connected: " << client_address << ":" << client_port
              << std::endl;

    auto t = std::make_shared<std::thread>(session, socket);
    thread_set.insert(t);
  }
}

int main() {
  try {
    boost::asio::io_context ioc;
    StartServer(ioc, 8888);
    for (auto &t : thread_set) {
      t->join();
    }
  } catch (std::exception &e) {
    std::cerr << "Exception " << e.what() << "\n";
  }
  return 0;
}